/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package de.bht.esa.weather.weatherresourceaggregator;

import de.bht.esa.weather.googlegeocodingclient.GoogleGeocodingClient;
import de.bht.esa.weather.model.Forecast;
import de.bht.esa.weather.model.Location;
import de.bht.esa.weather.model.WetterComForecast;
import de.bht.esa.weather.model.WetterComLocation;
import de.bht.esa.weather.remotebeaninterfaces.WeatherAggregationRequest;
import de.bht.esa.weather.remotebeaninterfaces.WeatherAggregationResponse;
import de.bht.esa.weather.remotebeaninterfaces.WeatherResourceManager;
import de.bht.esa.weather.weathersoapclient.WeatherService;
import de.bht.esa.weather.weathersoapclient.WeatherService_Service;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;

/**
 * Aggregiert eine Wetter-Anfrage zu einem Wetterbericht und einer Location
 * 
 * @author Andreas Goese
 * @author Sven Höche
 */
@MessageDriven(mappedName = "WeatherQueue" , activationConfig = {
    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
    @ActivationConfigProperty(propertyName = "destination", propertyValue = "WeatherQueue")
})
public class WeatherresourceAggregator implements MessageListener{
    
    private final static Logger LOG = Logger.getLogger(WeatherresourceAggregator.class.getName());

    
    @EJB(lookup="de.bht.esa.weather.remotebeaninterfaces.WeatherResourceManager")
    WeatherResourceManager resourceManager;
    
    /**
     * Arbeitet die WeatherQueue ab. Wird aufgerufen wenn sich Messages in der Queue befinden.
     * Die Message kann entweder Koordinaten oder einen Suchstring für einen Ort enthalten. Je nachdem müssen 
     * die Koordinaten bei Google abgerufen werden um den Ort auf der Karte anzeigen zu können, oder der Ort
     * für die gegebenen Koordinaten um den Ort bei Wetter.com anfragen zu können.
     * 
     * Ist die Aggregation abgeschlossen, wird die fertige Vorhersage über den ResourceManager gespeichert.
     * 
     * @param message 
     */
    @Override
    public void onMessage(Message message) {
        WeatherAggregationRequest request;
        try{
            ObjectMessage msg = (ObjectMessage)message;
            request = (WeatherAggregationRequest)msg.getObject();            
        }catch(JMSException jmsex){
            throw new EJBException(jmsex);
        }
        
        try{
            String locationQuery = "";
            Location loc = new Location();
            if(request.getCoordinates() != null){//Coordinates given
                GoogleGeocodingClient geocoder = new GoogleGeocodingClient();
                loc = geocoder.reverseGeocode(request.getCoordinates(), false);
                locationQuery = loc.toString();
            }else if(request.getLocationQuery() != null){//Query given
                locationQuery = request.getLocationQuery();
                WetterComLocation[] tmpLocations = resourceManager.searchLocation(locationQuery);
                if(tmpLocations.length > 0){
                    locationQuery = tmpLocations[0].toString();
                }
                GoogleGeocodingClient geocoder = new GoogleGeocodingClient();
                loc = geocoder.geocode(locationQuery,false);
            }
            
            WetterComLocation[] tmpLocations = resourceManager.searchLocation(locationQuery);
            if(tmpLocations.length > 0){
                WeatherService_Service proxy = new WeatherService_Service();
                WeatherService service = proxy.getWeatherServicePort();
                de.bht.esa.weather.weathersoapclient.WetterComForecast forecast = service.getForecast(tmpLocations[0].getCityCode());
                
                WetterComForecast resultForecast = this.convertToNativeForecast(forecast);
                
                resultForecast.setLocation(tmpLocations[0]);
                resultForecast.getLocation().setBounds(loc.getBounds());
                resultForecast.getLocation().setCenter(loc.getCenter());
                
                WeatherAggregationResponse response = new WeatherAggregationResponse();
                response.setRequest(request);
                response.setForecast(resultForecast);
                resourceManager.saveWeatherAggregationResponse(response);
            }else{
                WeatherAggregationResponse response = new WeatherAggregationResponse();
                response.setRequest(request);
                response.setError("City-Code not found");
                resourceManager.saveWeatherAggregationResponse(response);
            }
                                   
        }catch(Exception ex){
            WeatherAggregationResponse response = new WeatherAggregationResponse();
            response.setRequest(request);
            response.setError(ex.getMessage());
            if(response.getError() == null){
                response.setError("Error");
            }
            resourceManager.saveWeatherAggregationResponse(response);
            Logger.getLogger(WeatherresourceAggregator.class.getName()).log(Level.WARNING, "OnMessage failed: " + ex.getMessage(), ex);
        }
    }
    
    private WetterComForecast convertToNativeForecast(de.bht.esa.weather.weathersoapclient.WetterComForecast inForecast){
        WetterComForecast outForecast = new WetterComForecast();
        outForecast.setDetailUrl(inForecast.getDetailUrl());   
        outForecast.setForecast(new Forecast());
        outForecast.getForecast().setWeatherTxt(inForecast.getForecast().getWeatherTxt());
        outForecast.getForecast().setLocalTimestamp(inForecast.getForecast().getLocalTimestamp());
        outForecast.getForecast().setMaxTemp(inForecast.getForecast().getMaxTemp());
        outForecast.getForecast().setMinTemp(inForecast.getForecast().getMinTemp());
        outForecast.getForecast().setPredictionPeriod(inForecast.getForecast().getPredictionPeriod());
        outForecast.getForecast().setRainChance(inForecast.getForecast().getRainChance());
        outForecast.getForecast().setUtcTimestamp(inForecast.getForecast().getUtcTimestamp());
        outForecast.getForecast().setWeatherCode(inForecast.getForecast().getWeatherCode());
        outForecast.getForecast().setWindDirection(inForecast.getForecast().getWindDirection());
        outForecast.getForecast().setWindDirectionText(inForecast.getForecast().getWindDirectionText());
        outForecast.getForecast().setWindSpeed(inForecast.getForecast().getWindSpeed());
        return outForecast;
    }
    
}
